import * as THREE from "three";

// 引入轨道控制器控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
// 引入动画库
import gsap from "gsap";
// 引入数据图形用户界面库
import * as dat from "dat.gui";
// 引入rgbeLoad
// DataTextureLoader
// 用于加载二进制文件格式的(rgbe, hdr, ...)的抽象类。 内部使用FileLoader来加载文件， 和创建一个新的 DataTexture.
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js"
// 引入物理引擎
import * as CANNON from 'cannon-es';
// 用于载入glTF 2.0资源的加载器。
// glTF（gl传输格式）是一种开放格式的规范 （open format specification）， 用于更高效地传输、加载3D内容。
// 该类文件以JSON（.gltf）格式或二进制（.glb）格式提供， 外部文件存储贴图（.jpg、.png）和额外的二进制数据（.bin）。
// 一个glTF组件可传输一个或多个场景， 包括网格、材质、贴图、蒙皮、骨架、变形目标、动画、灯光以及摄像机。
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"

// 导入官方例子中使用的水实现 需要导入材质纹理
import { Water } from 'three/examples/jsm/objects/Water2.js';

//three.js 基本内容

// 1.创建场景  场景能够让你在什么地方、摆放什么东西来交给three.js来渲染，这是你放置物体、灯光和摄像机的地方。
const scene = new THREE.Scene();

// 2.创建相机 
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 300);

//2.1设置相机的位置 position表示对象局部位置的Vector3。默认值为(0, 0, 0)。
camera.position.set(0, 1, 2);
scene.add(camera); //添加相机到场景中

// 设置水参数
// const params = {
//     color: '#26baff',
//     scale: 1,
//     flowX: 1,
//     flowY: 1
// };
// const water = new Water( new THREE.PlaneBufferGeometry(1, 1, 1024, 1024), {
//     color: params.color,
//     scale: params.scale,
//     flowDirection: new THREE.Vector2( params.flowX, params.flowY ),
//     textureWidth: 1024,
//     textureHeight: 1024
// } );
// water.rotation.x = - Math.PI / 2;
// console.log(water)

// scene.add(water);

// 加载hrd环境纹理
const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync("./texture/050.hdr").then((texture) => {
    // console.log(texture)
    // 图像将如何应用到物体（对象）上。
    texture.mapping = THREE.EquirectangularReflectionMapping;
    // 设置场景背景 物理材质的环境贴图
    scene.background = texture;
    scene.environment = texture;
});
// 加载浴缸
const gltfLoader = new GLTFLoader();
gltfLoader.load("./model/yugang.glb", (gltf) => {
    console.log(gltf);
    // console.log(gltf.scene.children);
    let yugang = gltf.scene.children[0];
    yugang.material.side = THREE.DoubleSide;
    // console.log(gltf.scene.children[0]);
    // scene.add(yugang); //add后 gltf.scene.children-1;
    // console.log(gltf.scene.children[0]);

    
  const waterGeometry = gltf.scene.children[1].geometry;
  const water = new Water(waterGeometry, {
    color: "#ffffff",
    scale: 1,
    flowDirection: new THREE.Vector2(1, 1),
    textureHeight: 1024,
    textureWidth: 1024,
  });
  //物体添加放最后 
  scene.add(yugang);
  scene.add(water);
})

// 添加灯光
// 添加环境光
const light = new THREE.AmbientLight(0xffffff, 3);

scene.add(light);


// 4.渲染
// 初始化渲染器
// WebGLRenderer WebGL Render 用WebGL渲染出你精心制作的场景。
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// .domElement : DOMElement   一个canvas，渲染器在其上绘制输出。
// 渲染器的构造函数会自动创建(如果没有传入canvas参数);你需要做的仅仅是像下面这样将它加页面里去:
document.body.appendChild(renderer.domElement); //将绘制canvas添加到页面里
// 开启场景中的阴影贴图
// renderer.shadowMap.enabled = true;
// renderer.physicallyCorrectLights = true; // 新版本不用设置 物理正确光源 decay也会生效。 老版本开阴影要设置


//创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;

// 创建坐标轴辅助器
// AxesHelper  用于简单模拟3个坐标轴的对象.
// 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
// AxesHelper( size : Number )  size -- (可选的) 表示代表轴的线段长度. 默认为 1.
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

// 设置时钟
const clock = new THREE.Clock();


function render() {
    let elapsedTime = clock.getElapsedTime();
    controls.update();
    renderer.render(scene, camera);
    // requestAnimationFrame 是一个用于优化浏览器动画效果的 API。它可以让浏览器在下一次重绘前执行指定的回调函数，
    // 从而可以更加流畅地执行动画效果，避免了使用 setTimeout 或 setInterval 可能引起的性能问题。
    requestAnimationFrame(render);
}

render();

// 窗口变化时，更新渲染画面
window.addEventListener("resize", () => {

    // 更新摄像机视锥体长宽比
    camera.aspect = window.innerWidth / window.innerHeight;
    // 更新摄像机投影矩阵。在任何参数被改变以后必须被调用
    camera.updateProjectionMatrix();

    // 更新渲染器
    renderer.setSize(window.innerWidth, window.innerHeight);
    // 设置渲染器像素比 通常用于避免HiDPI设备上绘图模糊
    renderer.setPixelRatio(window.devicePixelRatio);

})


